﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace UnityTouchTable.Runtime
{
    /// <summary>
    /// 角度均分器
    /// </summary>
    [AddComponentMenu("TouchTable/AngleEqualizer", 3)]
    [DisallowMultipleComponent]
    public class AngleEqualizer : MonoBehaviour, IAnglehandle
    {
        #region EventHandler
        /// <summary>
        /// 当角度区域索引改变
        /// </summary>
        private EventHandler m_OnChangeAngleIndex;
        #endregion

        #region Event
        /// <summary>
        /// 角度区域索引改变
        /// </summary>
        public event EventHandler ChangeAngleIndex
        {
            add => this.m_OnChangeAngleIndex += value;
            remove => this.m_OnChangeAngleIndex -= value;
        }
        #endregion

        #region Field
        /// <summary>
        /// 当移动时是否更新角度
        /// </summary>
        [SerializeField]
        [Header("当移动时是否更新角度")]
        private bool m_OnMoveUpdateAngle = false;

        /// <summary>
        /// 均分数量
        /// </summary>
        [SerializeField]
        [Header("均分数量")]
        [Range(2, 12)]
        private int m_Count = 6;

        /// <summary>
        /// 单位角度
        /// </summary>
        private float m_UnitAngle;

        /// <summary>
        /// 角度区域索引
        /// </summary>
        private int m_AngleIndex;

        /// <summary>
        /// 下一个角度区域索引
        /// </summary>
        private int m_NextAngleIndex;

        /// <summary>
        /// 容忍角度
        /// </summary>
        [SerializeField]
        [Header("容忍角度")]
        [Range(1.0f, 10.0f)]
        private float m_ToleranceAngle = 3.0f;

        /// <summary>
        /// 角度停留时长
        /// </summary>
        [SerializeField]
        [Header("角度停留时长")]
        [Range(0.1f, 1.0f)]
        private float m_AngleStayTime = 0.25f;

        /// <summary>
        /// 能否计时
        /// </summary>
        private bool m_CanTimer;

        /// <summary>
        /// 计时器
        /// </summary>
        private float m_Timer;
        #endregion

        #region Property
        /// <summary>
        /// 设置或获取均分数量
        /// </summary>
        public int Count
        {
            get => this.m_Count;
            set => this.m_Count = value;
        }

        /// <summary>
        /// 获取当移动时是否更新角度
        /// </summary>
        public bool OnMoveUpdateAngle => this.m_OnMoveUpdateAngle;
        #endregion

        private void Update()
        {
            if (!this.m_CanTimer)
                return;

            this.m_Timer += Time.deltaTime;
            if (this.m_Timer >= this.m_AngleStayTime)
            {
                this.m_AngleIndex = this.m_NextAngleIndex;
                this.m_CanTimer = false;
                this.m_Timer = 0.0f;

                ChangeAngleIndexEventArgs changeAngleIndexEventArgs = ChangeAngleIndexEventArgs.Get();
                changeAngleIndexEventArgs.AngleIndex = this.m_AngleIndex;
                changeAngleIndexEventArgs.UnitAngle = this.m_UnitAngle;
                this.m_OnChangeAngleIndex?.Invoke(this, changeAngleIndexEventArgs);
                changeAngleIndexEventArgs.Dispose();
            }
        }

        #region Function
        /// <summary>
        /// 更新角度
        /// </summary>
        /// <param name="angle">角度</param>
        public void UpdateAngle(float angle)
        {
            this.m_UnitAngle = 360.0f / this.m_Count;
            int floor = (int)(angle / this.m_UnitAngle);

            if (floor == this.m_AngleIndex)
            {
                this.m_CanTimer = false;
                this.m_Timer = 0.0f;
                return;
            }

            //角度差
            float angleDifference = Mathf.Abs((this.m_AngleIndex + 0.5f) * this.m_UnitAngle - angle);
            angleDifference -= this.m_UnitAngle * 0.5f;
            if (angleDifference < this.m_ToleranceAngle)
            {
                this.m_CanTimer = false;
                this.m_Timer = 0.0f;
                return;
            }

            this.m_CanTimer = true;
            if (this.m_NextAngleIndex != floor)
            {
                this.m_NextAngleIndex = floor;
                this.m_Timer = 0.0f;
            }
        }
        #endregion
    }
}